package com.sise.stuteaintersys.controller;

import com.alibaba.fastjson.JSON;
import com.sise.stuteaintersys.bean.base.ChatMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @ClassName ConsultWebSocket
 * @Description 使用WebSocket实现聊天功能
 * @Date 2018/12/20 11:32
 * @Version 1.0
 **/
@RestController
@ServerEndpoint("/consult/{roomName}")
@Slf4j
public class ConsultWebSocket {

    /**
     * 使用map来收集session，key为roomName，value为同一个房间的用户集合
     */
    private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap<>();

    /**
     * 缓存session对应的用户
     */
    private static final Map<String, String> users = new ConcurrentHashMap<>();

    @OnOpen
    public void connect(@PathParam("roomName") String roomName, Session session) throws IOException {
        String[] strings = roomName.split("-");
        roomName = strings[0];
        String name = strings[1];
        //随机获取的名字
        log.info(name);
        // 将session按照房间名来存储，将各个房间的用户隔离
        if (!rooms.containsKey(roomName)) {
            // 创建房间不存在时，创建房间
            Set<Session> room = new HashSet<>();
            // 添加用户
            room.add(session);
            rooms.put(roomName, room);
        } else {
            // 房间已存在，直接添加用户到相应的房间
            rooms.get(roomName).add(session);
        }

        users.put(session.getId(), name);

        //向上线的人发送当前在线的人的列表
        List<ChatMessage> userList = new LinkedList<>();
        rooms.get(roomName)
                .stream()
                .map(Session::getId)
                .forEach(s -> {
                    ChatMessage chatMessage = new ChatMessage();
                    chatMessage.setDate(new Date());
                    chatMessage.setUserName(name);
                    chatMessage.setChatContent(users.get(s) + "在线");
                    //遍历所有人，添加到列表里
                    userList.add(chatMessage);
                });
        session.getBasicRemote().sendText(JSON.toJSONString(userList));

        //向房间的所有人广播谁上线了
        broadcast(roomName, name+"上线了");

    }

    @OnClose
    public void disConnect(@PathParam("roomName") String roomName, Session session) {
        String[] strings = roomName.split("-");
        roomName = strings[0];
        String name = strings[1];
        rooms.get(roomName).remove(session);
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setDate(new Date());
        chatMessage.setUserName(name);
        chatMessage.setChatContent(users.get(session.getId()) + "下线了");
        users.remove(session.getId());
        broadcast(roomName, JSON.toJSONString(chatMessage));
        log.info("<<<<<<<<<<<<<a client has disconnected!>>>>>>>>>>>>>>");
    }

    /**
     * @param msg 前台传回来的数据应为json数据
     */
    @OnMessage
    public void receiveMsg(@PathParam("roomName") String roomName,
                           String msg, Session session) {
        String[] strings = roomName.split("-");
        roomName = strings[0];
        // 此处应该有html过滤，进行数据加工
        msg = users.get(session.getId()) + ":" + msg;
        // 接收到信息后进行广播
        broadcast(roomName, msg);
    }

    /**
     * 发送图片，视频，语音等
     *
     * @param name     用户名
     * @param roomName 房间id
     * @param file     上传的文件
     */
    @PostMapping("/consult/{roomName}/{name}")
    public void file(@PathVariable("name") String name, @PathVariable("roomName") String roomName, MultipartFile file) {
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setDate(new Date());
        chatMessage.setUserName(name);
        chatMessage.setChatContent(file.getName());
        broadcast(roomName, JSON.toJSONString(chatMessage));
    }

    /**
     * 按照房间名进行广播
     * @param roomName
     * @param msg
     */
    private void broadcast(String roomName, String msg) {
        rooms.get(roomName).forEach(s -> {
            try {
                s.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
//        //将聊天记录加入缓存
//        //这里需要将此服务层的bean手动注入
//        if (chatCacheService == null) {
//            chatCacheService = ApplicationContextRegister.getApplicationContext().getBean(ChatCacheService.class);
//        }
//        chatCacheService.cacheMsg(msg, roomName, CacheType.CONSULT);
    }

}
